﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Red.Core.DataConsistency
{
    /// <summary>
    /// An actively listening group for tracked states
    /// It's possible to bind an user callback that will be called whenever state change will occur 
    /// that will make any of the tokens registered in this group inconsistent.
    /// NOTE: please make sure you ALWAYS Dispose() those objects when not used
    /// </summary>
    public class StateGroup : IDisposable
    {
        //----------------

        public delegate void StateEventHandler(StateGroup group);
        public event StateEventHandler OnStateChanged;

        public delegate void StateUnregisterFunction(StateGroup group);

        //----------------

        /// <summary>
        /// Initialization of the state group
        /// </summary>
        /// <param name="debugName"></param>
        internal StateGroup(string debugName, UInt32 groupID, UInt32 groupGeneration, StateUnregisterFunction funcUnregister)
        {
            DebugName = debugName;
            GroupID = groupID;
            GroupGeneration = groupGeneration;
            _FuncUnregister = funcUnregister;
        }

        /// <summary>
        /// Object disposed
        /// </summary>
        public void Dispose()
        {
            // cleanup
            if (GroupID != 0)
            {
                _FuncUnregister(this);
                _FuncUnregister = null;
                GroupID = 0;
            }

            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Dispatch callback event for this group signaling any lister that objects tracked in this group have been modified
        /// </summary>
        public void DispatchEvent()
        {
            if (OnStateChanged != null)
                OnStateChanged( this );
        }

        /// <summary>
        /// Internal debugging only name
        /// </summary>
        public readonly string DebugName;

        /// <summary>
        /// Incremental GlobalID for the state group
        /// </summary>
        public UInt32 GroupID { get; private set; }

        /// <summary>
        /// Always increasing global monotonic ID of group operations
        /// Helps to identify if two GroupIDs actually mean the same group
        /// </summary>
        public UInt32 GroupGeneration { get; private set; }

        /// <summary>
        /// Global state synchronizer that owns this group
        /// </summary>
        private StateUnregisterFunction _FuncUnregister;
    }
}
